;(function($){
    if ($ == undefined){
        throw "missing jQuery";
    }
    var token = null;
    var webmcs = {};
    webmcs.login = {};
    webmcs.server = {};
    webmcs.setting = {};
    webmcs.task = {};
    webmcs.file = {};
    /** webmcs common **
    callback   = "callback 回调函数，如果不填写则使用同步请求，返回请求结果。如果填写则发送异步请求，通过回调函数传回调用结果，传回结果同函数返回值一致"
    notlogin   = "NOTLOGIN      = 没有登录账号，接口调用失败"
    neterror   = "NETERROR         = 网络错误接口调用失败"
    tokenerror = "TOKENERROR    = token令牌错误"
    **/
    /** webmcs **
     * name 初始化函数，必须调用，成功后自动调用callback
     * param callback 回调函数
     * param errorCallback 初始化失败时回调函数
     */
    webmcs.init = function(callback, errorCallback){
        $.ajax({
            'url': 'security/getToken.security',
            'type': 'get',
            'cache': false,
            'dataType': 'text',
            'success': function(data){
                token = data;
                callback();
            },
            'error': function(){
                errorCallback();
            }
        });
    }
    /** webmcs **
     * name 获取token令牌
     * return 返回令牌内容或者null，如果返回null应当检查token初始化是否失败
     **/
    webmcs.getToken = function(){
      return token;
    }
    webmcs.getVersion = function(){
      return "1.1.3.4";
    }
    webmcs.getVersionCode = function(){
      return 1134;
    }
    /** webmcs **
     * name 获取登录用户的用户名，可用于判断登录状态
     * param {{callback}}
     * return 返回{status: status}对象，如果登录成功status=true，且额外返回name字段，登录失败返回false
     **/
    webmcs.login.getUsername = function(callback){
        return  getHtml("login/getusername.login",callback);
    }
    /** webmcs **
     * name 注销登录状态，无返回值，调用后请自行刷新登录状态
     * param {{callback}}
     **/
    webmcs.login.logout = function(callbcak){
        getHtml("login/loginout.login",callbcak);
    }
    /** webmcs **
     * name 判断是否需要初始化(注册还是登录)
     * param {{callback}}
     * return 返回{isfirst: isfirst}对象，如果是第一次初始化值为true，否则为false
     **/
    webmcs.login.isInit = function(callback){
        return getHtml("login/isfirst.login",callback);
    }
    /** webmcs **
     * name 根据账号密码进行登录
     * param name 用户名
     * param pwd 密码
     * param code 验证码，可以通过login/image.login接口获取验证码图片
     * param saveLoginstatus 记住登陆状态，true则记住7天登陆状态，false则不记住登陆状态
     * param {{callback}}
     * return 返回{status: status, msg: msg}对象，如果调用成功则status=true，失败返回false且返回msg字段。可能的值有
     *          CHECKERROR   = 账号密码错误
     *          CODEERROR    = 验证码错误
     *          ALREADYLOGIN = 已登录
     *          {{neterror}}
     *          如果返回null，说明接口调用成功
     **/
    webmcs.login.login = function(name, pwd, code, saveLoginStatus, callback){
        return postHtml("login/login.login", {username : name,
                                                   password : pwd,
                                                   saveLoginStatus : saveLoginStatus,
                                                   code : code}, callback);
    }
    /** webmcs **
     * name 注册账号，仅能使用一次，可根据webmcs.login.isInit接口判断是否可以注册
     * param name 用户名
     * param pwd 密码
     * param {{callback}}
     * return 返回{status: status, msg: msg}对象，如果调用成功则status=true，失败返回false且返回msg字段。可能的值有
     *          ALREADYINIT = 已初始化(已注册过账号)
     *        PARAMERROR  = 传递参数错误
     *          {{neterror}}
     *          如果返回null，说明接口调用成功
     **/
    webmcs.login.register = function(name, pwd, callback){
        return postHtml("login/init.login", {username : name, password : pwd}, callback);
    }
    /** webmcs **
     * name 获取服务器回显消息 
     * param uuid 消息uuid，可以不填写。如果不填写则拉取服务器缓冲区中所有消息
     * param {{callback}}
     * return 执行成功时返回 {message: message, uuid: uuid, status: status} 对象
     * message为服务器拉取的回显消息
     * uuid为最后一条记录的uuid，用于传递给本接口再次重复调用
     * status为接口请求状态，true=服务器正在运行，false=服务器不在允许或账号未登录。如果是未登录则额外返回msg=NOLOGIN
     **/
    webmcs.server.getMessage = function(uuid, callback){
        uuid = uuid == undefined ? "" : uuid;
        return postHtml("core/server/message.mcs","uuid=" + uuid, callback);
    }
    /** webmcs **
     * name 开启MC服务器
     * param {{callback}}
     * return 返回{status: status,msg: msg}对象，成功时status=true，且无msg字段，失败时msg字段如下
     *        {{notlogin}}
     *        ALREADYSERVER = 服务器已运行，无法重复运行
     *        JARERROR      = JAR文件不存在或者未设置
     *        PROCESSERROR  = 进程创建失败，一般是Java或者启动命令错误导致的 
     *        {{neterror}}
     **/
    webmcs.server.start = function(callback){
        return getHtml("core/server/start.mcs", callback);
    }
    /** webmcs **
     * name 通过发送stop指令来关闭MC服务器
     * param {{callback}}
     * return 返回{status: status,msg: msg}对象，成功时status=true，且无msg字段，失败时msg字段如下
     *        {{notlogin}}
     *        SERVERNOTRUN  = 服务器不在运行，无法关闭
     *        UNKNOWNERROR  = 后台IO异常，一般不会出现这个错误。如果出现请检查报错并反馈给作者改进
     *        {{neterror}}
     **/
    webmcs.server.stop = function(callback){
        return getHtml("core/server/stop.mcs", callback);
    }
    /** webmcs **
     * name 使用终止进程的方式强制关闭正在运行的服务器
     * param {{callback}}
     * return 返回{status: status,msg: msg}对象，成功时status=true，且无msg字段，失败时msg字段如下
     *        SERVERNOTRUN  = 服务器不在运行，无法关闭
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.server.termination = function(callback){
        return getHtml("core/server/termination.mcs", callback);
    }
    /** webmcs **
     * name 发送文本消息给服务器
     * param message 欲发送给服务器的文本消息，如 help list 之类的Minecraft服务器指令
     * param {{callback}}
     * return 返回{status: status,msg: msg}对象，成功时status=true，且无msg字段，失败时msg字段如下
     *        SERVERNOTRUN  = 服务器不在运行，无法发送消息
     *        UNKNOWNERROR  = 后台IO异常，一般不会出现这个错误，如果出现请检查报错并反馈给作者改进
     *        {{notlogin}}
     *        {{neterror}}
     *
     **/
    webmcs.server.sendMessage = function(message, callback){
        return postHtml("core/server/send.mcs",{message:message}, callback);
    }
    /** webmcs **
     * name 通知后台重启服务器，请求后连接会被服务器挂起，直到重启成功或失败才会返回，请使用异步调用本接口
     * param {{callback}}
     * return 返回{status: status,msg: msg}对象，成功时status=true，且无msg字段，失败时msg字段如下
     *        SERVERNOTRUN  = 服务器不在运行，无法进行重启
     *        TIMEOUT       = 服务器超时，无法重启
     *        {{notlogin}}
     *        {{neterror}}
     *
     **/    
    webmcs.server.restart = function(callback){
        return getHtml("core/server/restart.mcs", callback);
    }
    /** webmcs **
    * name 获取服务端目前的运行状态
    * param {{callback}}
    * return 返回{"status":true,"serverstate":true}对象，serverstate=true代表服务器正在运行，如果status为false，msg字段可能出现如下值
    *        {{notlogin}}
    *        {{neterror}}
    **/
    webmcs.server.getServerStatus = function(callback){
        return getHtml("core/server/status.mcs", callback);
    }
    /** webmcs **
    * name 获取目前服务器文件中可选择用作开服的jar文件列表
    * param {{callback}}
    * return 返回{"status":true,"files" : ["a.jar","b.jar"]}，如果status为false，msg可能出现如下值
    *        {{notlogin}}
    *        {{neterror}}
    **/
    webmcs.setting.getjars = function(callback){
        return getHtml("setting/getjar.mcs", callback);
    }
    /** webmcs **
     * name 保存服务器设置
     * param json 服务器设置的JSON文本，如{javaParam: "-server"}，目前支持的配置包括：
     *        javaParam(java启动参数)
     *        javaPath(java路径)
     *        jarPath(jar文件名)
     *        startParam(jar启动参数)
     *        maxMemory(最大内存)
     * param {{callback}}
     * return 返回{status: true}，如果失败，额外返回msg字段，可能的值如下
     *        {{neterror}}
     *        {{notlogin}}
     **/
    webmcs.setting.savesetting = function(json, callback){
        return postHtml("setting/setsetting.mcs", {json: json}, callback);
    }
    /** webmcs **
     * name 读取服务器文件列表（只显示出名称中带java的文件，用于设置java路径功能）
     * param path 目录路径，可以传递空文本代表获取根目录数据
     * param {{callback}}
     * return 成功额外返回files[]字段，格式为[0]=路径 [1]=类型 [2]=时间 [3] = 文件名，如
{status:true,files:[["/usr/bin","File","2016-08-21","java"],["/usr/bin","File","2016-08-21","javac"]]}，失败返回status=false和msg字段，值可能如下
     *        {{neterror}}
     *        {{notlogin}}
     **/
    webmcs.setting.getfiles = function(path, callback){
        return postHtml("setting/getfiles.mcs", {path: path}, callback);
    }
    /** webmcs print **
     * url setting/uploadjar.mcs
     * name 文件上传接口，用于上传.jar文件到server目录内，用于设置服务端启动文件 
     * param 待上传文件，name = file，只支持单文件，如果强行上传多文件，那么将会只保存第一个文件
     * return 成功无额外返回字段。失败时msg返回以下字段:
     *        TYPEERROR -> 文件类型错误，只支持jar文件
     *        EXCEPTION -> 服务器内部异常，如果遇到请反馈给开发者
     *        FILEREPEAT -> 文件名与服务器内已有文件重复
     *        CHECKERROR -> 检验未通过，如果遇到请提交浏览器版本给开发者修复问题
     *        {{notlogin}}
     **/
    /** webmcs **
     * name 读取服务器配置
     * param {{callback}}
     * return 成功返回软件设置数据，如{status:true,javaPath:"/usr/bin/java"}，支持参数见webmcs.setting.savesetting方法注释。失败时msg可能返回以下值
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.setting.getsetting = function(callback){
        return getHtml("setting/getsetting.mcs", callback);
    }
    /** webmcs **
     * name 获取计划任务列表
     * param {{callback}}
     * return 成功额外返回list字段，是一个嵌套两层的数组。第一层是计划任务数量，第二层是计划任务详细数据。第二层中 [0]=id [1]=type [2]=content [3]=time [4]=exectype，示例如下
{status:true,list:[["id1","1","1","10","1"],["id2","2","say test","10","2"]]}。如果请求失败，status=false，额外返回msg字段，可能的值如下：
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.task.gettasks = function(callback){
        return getHtml("core/task/gettasks.mcs", callback);
    }
    /** webmcs **
     * name 移除一个计划任务
     * param id 对应gettasks接口中传递的id
     * param {{callback}}
     * return 成功无额外返回字段，失败时msg返回如下字段:
     *        IDERROR -> ID错误
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.task.deltask = function(taskId, callback){
        return postHtml("core/task/deltask.mcs", {id : taskId}, callback);
    }
    /** webmcs **
     * name 增加一个新的计划任务
     * param paramText 需要发送给服务器的参数，应当拼接成key=value&key2=value2的形式，建议使用jquery的serialize方法，具体传递值说明如下
     *                    type -> 计划任务类型(1=系统任务 2=指令任务)
     *                    sys_content -> 系统任务内容(仅限type=1时生效，1=开启服务器 2=关闭服务器 3=重启服务器 4=备份地图)
     *                    cmd_content -> 指令任务内容(仅限type=2时生效，直接传递需要被定期执行的指令)
     *                    exectype -> 任务周期类型(1=周期性任务 2=一次性任务)
     *                    time -> 执行周期(单位为分钟，只接受正整数)
     * param {{callback}}
     * return 成功无额外返回字段，失败时msg返回如下字段:
     *            PARAMERROR -> 参数错误
     *            {{notlogin}}
     *            {{neterror}}
     **/
    webmcs.task.addtask = function(paramText, callback){
        return postHtml("core/task/addtask.mcs", paramText, callback);
    }
    /** webmcs **
     * name 获取服务器文件列表
     * param path 服务器文件路径，如果要读取根目录请输入/
     * param {{callback}}
     * return 成功额外返回dir数组和files数组
     *        dir[0] = 目录名称 dir[1] = 真实路径
     *        files[0] = 文件名称 files[1] = 文件名尺寸 files[2] = 文件最后修改日期 files[3] = 真实路径
              失败时额外返回msg字段，可能的值如下
     *        PATHERROR -> 路径参数错误
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.file.getfiles = function(path, callback){
        return postHtml("core/file/getfiles.mcs", {path : path}, callback);
    }
    /** webmcs **
     * name 在服务器server中创建一个目录
     * param dirPath 服务器文件夹完整路径，从/开始代表server根目录，如/test/a，将会在服务器server目录下连续创建test和a两个文件夹
     * param {{callback}}
     * return 成功无额外返回值，失败时返回msg字段说明失败原因，可能的值如下
     *          PARAMERROR -> 参数错误
     *        DIREXITS -> 目录已存在
     *          NAMEERROR -> 文件名称错误
     *          {{notlogin}}
     *          {{neterror}}
     **/
    webmcs.file.mkdir = function(dirPath, callback){
        return postHtml("core/file/mkdir.mcs", {path : dirPath}, callback);
    }
    /** webmcs ** 
     * name 在服务器server中删除一个或多个目录
     * param files 文件路径数组，如['/world', '/logs']，支持递归删除子目录
     * param {{callback}}
     * return 成功无额外返回值，失败时返回msg字段说明失败原因，可能的值如下
     *        PARAMERROR -> 参数错误
     *        UNKNOWNERROR -> 删除出现异常（例如文件被占用等未考虑到的任意特殊情况）
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.file.delfiles = function(files, callback){
        return postHtml("core/file/delfiles.mcs", arrayToSubmitText(files, 'fileName'), callback);
    }
    /** webmcs **
     * name 在服务器上压缩server内的指定文件，请求（回调）将会被挂起，直到压缩完毕
     * param fileNames 文件名称数组
     * param saveFile 保存文件名称
     * param {{callbcak}}
     * return 成功无额外返回值，失败时返回msg字段说明失败原因，可能的值如下
     *        PARAMERROR -> 参数错误
     *        EXCEPTION -> 压缩出现异常
     *        {{notlogin}}
     *        {{neterror}}
     **/
    webmcs.file.compressFiles = function(fileNames, saveFile, callback){
        return postHtml("core/file/compressFiles.mcs", 
                        arrayToSubmitText(fileNames, 'fileName') + '&saveFile=' + encodeURIComponent(saveFile), 
                        callback);
    }
    webmcs.file.copyFiles = function(fileNames, destDir, callback){
        return postHtml("core/file/copyFiles.mcs",
                        arrayToSubmitText(fileNames, 'fileName') + '&destDir=' + encodeURIComponent(destDir),
                        callback);
    }
    webmcs.file.moveFiles = function(fileNames, destDir, callback){
        return postHtml("core/file/moveFiles.mcs",
                        arrayToSubmitText(fileNames, 'fileName') + '&destDir=' + encodeURIComponent(destDir),
                        callback);
    }
    webmcs.file.unCompress = function(filePath, dir, callback){
        return postHtml("core/file/unCompress.mcs", {filePath: filePath, destDir: dir}, callback);
    }
    webmcs.file.getFileContent = function(filePath, encoding, callback){
        return postHtml("core/file/getFileContent.mcs", {path: filePath, encoding: encoding}, callback);
    }
    webmcs.file.putFileContent = function(path, content, encoding, callback){
        return postHtml("core/file/putFileContent.mcs", {path: path, content: content, encoding: encoding}, callback);
    }
    webmcs.file.renameFile = function(path, filename, callbcak){
        return postHtml("core/file/renameFile.mcs", {path: path, filename: filename}, callbcak);
    }
    window.webmcs = webmcs;
    //从数组转换为提交文本参数
    function arrayToSubmitText(arr, name){
        var submitText = '';
        for(var i=0;i<arr.length;i++){
            if(i != 0){
                submitText += '&';
            }
            submitText += name + '=' + encodeURIComponent(arr[i]);
        }
        return submitText;
    }
    function getHtml(url,callback){
        var async = callback==undefined ? false : true;
        if (url.indexOf('?') != -1){
            url += "&token=" + token;
        }else{
            url += "?token=" + token;
        }
        var obj = $.ajax({
            url : url,
            async : async,
            dataType : 'json',
            success : function(data){
                if(async){
                   callback(data); 
                }
            },
            error : function(){
                if(async){
                    callback({status: false, msg: 'NETERROR'});
                }
            }
        });
        if (obj.readyState == 4){
            try{
                return JSON.parse(obj.responseText)
            }catch(e){
                return obj.responseText;
            }
        }
        return {status:false,msg:"NETERROR"};
    }
    function postHtml(url,data,callback){
        var async = callback==undefined ? false : true;
        if (url.indexOf('?') != -1){
            url += '&token=' + token;
        }else{
            url += '?token=' + token;
        }
        var obj = $.ajax({
            url : url,
            data : data,
            type : 'POST',
            async : async,
            dataType : 'json',
            success : function(data){
                if (async){
                    callback(data);
                }
            },
            error : function(){
                if (async){
                    callback({status: false, msg: 'NETERROR'});
                }
            }
        });
        if (obj.readyState == 4){
            try{
                return JSON.parse(obj.responseText);
            }catch(e){
                return obj.responseText;
            }
        }
        return {status:false,msg:"NETERROR"};
    }
})(jQuery);
